home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_tent.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-07  |  47.4 KB  |  1,960 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // cl_tent.c -- client side temporary entities
  21.  
  22. #include "client.h"
  23.  
  24. typedef enum
  25. {
  26.     ex_free, ex_explosion, ex_misc, ex_flash, ex_mflash, ex_poly, ex_poly2
  27. } exptype_t;
  28.  
  29. typedef struct
  30. {
  31.     exptype_t    type;
  32.     entity_t    ent;
  33.  
  34.     int            frames;
  35.     float        light;
  36.     vec3_t        lightcolor;
  37.     float        start;
  38.     int            baseframe;
  39. } explosion_t;
  40.  
  41.  
  42.  
  43. #define    MAX_EXPLOSIONS    32
  44. explosion_t    cl_explosions[MAX_EXPLOSIONS];
  45.  
  46.  
  47. #define    MAX_BEAMS    32
  48. typedef struct
  49. {
  50.     int        entity;
  51.     int        dest_entity;
  52.     struct model_s    *model;
  53.     int        endtime;
  54.     vec3_t    offset;
  55.     vec3_t    start, end;
  56. } beam_t;
  57. beam_t        cl_beams[MAX_BEAMS];
  58. //PMM - added this for player-linked beams.  Currently only used by the plasma beam
  59. beam_t        cl_playerbeams[MAX_BEAMS];
  60.  
  61.  
  62. #define    MAX_LASERS    32
  63. typedef struct
  64. {
  65.     entity_t    ent;
  66.     int            endtime;
  67. } laser_t;
  68. laser_t        cl_lasers[MAX_LASERS];
  69.  
  70. //ROGUE
  71. cl_sustain_t    cl_sustains[MAX_SUSTAINS];
  72. //ROGUE
  73.  
  74. //PGM
  75. extern void CL_TeleportParticles (vec3_t org);
  76. //PGM
  77.  
  78. void CL_BlasterParticles (vec3_t org, vec3_t dir);
  79. void CL_ExplosionParticles (vec3_t org);
  80. void CL_MuzzleParticles (vec3_t org);
  81. void CL_Leaderfield (vec3_t org);
  82. void CL_BFGExplosionParticles (vec3_t org);
  83. void CL_DustParticles (vec3_t org);
  84. // RAFAEL
  85. void CL_BlueBlasterParticles (vec3_t org, vec3_t dir);
  86.  
  87. struct sfx_s    *cl_sfx_ric1;
  88. struct sfx_s    *cl_sfx_ric2;
  89. struct sfx_s    *cl_sfx_ric3;
  90. struct sfx_s    *cl_sfx_lashit;
  91. struct sfx_s    *cl_sfx_spark5;
  92. struct sfx_s    *cl_sfx_spark6;
  93. struct sfx_s    *cl_sfx_spark7;
  94. struct sfx_s    *cl_sfx_railg;
  95. struct sfx_s    *cl_sfx_rockexp;
  96. struct sfx_s    *cl_sfx_grenexp;
  97. struct sfx_s    *cl_sfx_watrexp;
  98. // RAFAEL
  99. struct sfx_s    *cl_sfx_plasexp;
  100. struct sfx_s    *cl_sfx_footsteps[4];
  101.  
  102. struct model_s    *cl_mod_explode;
  103. struct model_s    *cl_mod_smoke;
  104. struct model_s    *cl_mod_flash;
  105. struct model_s    *cl_mod_parasite_segment;
  106. struct model_s    *cl_mod_grapple_cable;
  107. struct model_s    *cl_mod_parasite_tip;
  108. struct model_s    *cl_mod_explo4;
  109. struct model_s    *cl_mod_bfg_explo;
  110. struct model_s    *cl_mod_powerscreen;
  111. // RAFAEL
  112. struct model_s    *cl_mod_plasmaexplo;
  113.  
  114. //ROGUE
  115. struct sfx_s    *cl_sfx_lightning;
  116. struct sfx_s    *cl_sfx_disrexp;
  117. struct model_s    *cl_mod_lightning;
  118. struct model_s    *cl_mod_heatbeam;
  119. struct model_s    *cl_mod_monster_heatbeam;
  120. struct model_s    *cl_mod_explo4_big;
  121.  
  122. //CODERED
  123. struct model_s *cl_mod_blaster_muzzleflash;
  124.  
  125. //ROGUE
  126. /*
  127. =================
  128. CL_RegisterTEntSounds
  129. =================
  130. */
  131. void CL_RegisterTEntSounds (void)
  132. {
  133.     int        i;
  134.     char    name[MAX_QPATH];
  135.  
  136.     // PMM - version stuff
  137. //    Com_Printf ("%s\n", ROGUE_VERSION_STRING);
  138.     // PMM
  139.     cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav");
  140.     cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav");
  141.     cl_sfx_ric3 = S_RegisterSound ("world/ric3.wav");
  142.     cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav");
  143.     cl_sfx_spark5 = S_RegisterSound ("world/spark5.wav");
  144.     cl_sfx_spark6 = S_RegisterSound ("world/spark6.wav");
  145.     cl_sfx_spark7 = S_RegisterSound ("world/spark7.wav");
  146.     cl_sfx_railg = S_RegisterSound ("weapons/railgf1a.wav");
  147.     cl_sfx_rockexp = S_RegisterSound ("weapons/rocklx1a.wav");
  148.     cl_sfx_grenexp = S_RegisterSound ("weapons/grenlx1a.wav");
  149.     cl_sfx_watrexp = S_RegisterSound ("weapons/xpld_wat.wav");
  150.     // RAFAEL
  151.     // cl_sfx_plasexp = S_RegisterSound ("weapons/plasexpl.wav");
  152.     S_RegisterSound ("player/land1.wav");
  153.  
  154.     S_RegisterSound ("player/fall2.wav");
  155.     S_RegisterSound ("player/fall1.wav");
  156.  
  157.     for (i=0 ; i<4 ; i++)
  158.     {
  159.         Com_sprintf (name, sizeof(name), "player/step%i.wav", i+1);
  160.         cl_sfx_footsteps[i] = S_RegisterSound (name);
  161.     }
  162.  
  163. //PGM
  164.     cl_sfx_lightning = S_RegisterSound ("weapons/tesla.wav");
  165.     cl_sfx_disrexp = S_RegisterSound ("weapons/disrupthit.wav");
  166.     // version stuff
  167. //    sprintf (name, "weapons/sound%d.wav", ROGUE_VERSION_ID);
  168. //    if (name[0] == 'w')
  169. //        name[0] = 'W';
  170. //PGM
  171. }    
  172.  
  173. /*
  174. =================
  175. CL_RegisterTEntModels
  176. =================
  177. */
  178. void CL_RegisterTEntModels (void)
  179. {
  180.     cl_mod_explode = R_RegisterModel ("models/objects/explode/tris.md2");
  181.     cl_mod_smoke = R_RegisterModel ("models/objects/smoke/tris.md2");
  182.     cl_mod_flash = R_RegisterModel ("models/objects/flash/tris.md2");
  183.     cl_mod_parasite_segment = R_RegisterModel ("models/monsters/parasite/segment/tris.md2");
  184.     cl_mod_grapple_cable = R_RegisterModel ("models/ctf/segment/tris.md2");
  185.     cl_mod_parasite_tip = R_RegisterModel ("models/monsters/parasite/tip/tris.md2");
  186.     cl_mod_explo4 = R_RegisterModel ("models/objects/r_explode/tris.md2");
  187.     cl_mod_bfg_explo = R_RegisterModel ("sprites/s_bfg2.sp2");
  188.     cl_mod_powerscreen = R_RegisterModel ("models/items/armor/effect/tris.md2");
  189.     cl_mod_blaster_muzzleflash = R_RegisterModel ("sprites/s_bfg1.sp2");
  190.  
  191.     R_RegisterModel ("models/objects/laser/tris.md2");
  192.     R_RegisterModel ("models/objects/grenade2/tris.md2");
  193.     R_RegisterModel ("models/weapons/v_machn/tris.md2");
  194.     R_RegisterModel ("models/weapons/v_handgr/tris.md2");
  195.     R_RegisterModel ("models/weapons/v_shotg2/tris.md2");
  196.     R_RegisterModel ("models/objects/gibs/bone/tris.md2");
  197.     R_RegisterModel ("models/objects/gibs/sm_meat/tris.md2");
  198.     R_RegisterModel ("models/objects/gibs/bone2/tris.md2");
  199.     // RAFAEL
  200.     // re.RegisterModel ("models/objects/blaser/tris.md2");
  201.  
  202.     R_RegisterPic ("w_machinegun");
  203.     R_RegisterPic ("a_bullets");
  204.     R_RegisterPic ("i_health");
  205.     R_RegisterPic ("a_grenades");
  206.  
  207. //ROGUE
  208.     cl_mod_explo4_big = R_RegisterModel ("models/objects/r_explode2/tris.md2");
  209.     cl_mod_lightning = R_RegisterModel ("models/proj/lightning/tris.md2");
  210.     cl_mod_heatbeam = R_RegisterModel ("models/proj/beam/tris.md2");
  211.     cl_mod_monster_heatbeam = R_RegisterModel ("models/proj/widowbeam/tris.md2");
  212. //ROGUE
  213. }    
  214.  
  215. /*
  216. =================
  217. CL_ClearTEnts
  218. =================
  219. */
  220. void CL_ClearTEnts (void)
  221. {
  222.     memset (cl_beams, 0, sizeof(cl_beams));
  223.     memset (cl_explosions, 0, sizeof(cl_explosions));
  224.     memset (cl_lasers, 0, sizeof(cl_lasers));
  225.  
  226. //ROGUE
  227.     memset (cl_playerbeams, 0, sizeof(cl_playerbeams));
  228.     memset (cl_sustains, 0, sizeof(cl_sustains));
  229. //ROGUE
  230. }
  231.  
  232. /*
  233. =================
  234. CL_AllocExplosion
  235. =================
  236. */
  237. explosion_t *CL_AllocExplosion (void)
  238. {
  239.     int        i;
  240.     int        time;
  241.     int        index;
  242.     
  243.     for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  244.     {
  245.         if (cl_explosions[i].type == ex_free)
  246.         {
  247.             memset (&cl_explosions[i], 0, sizeof (cl_explosions[i]));
  248.             return &cl_explosions[i];
  249.         }
  250.     }
  251. // find the oldest explosion
  252.     time = cl.time;
  253.     index = 0;
  254.  
  255.     for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  256.         if (cl_explosions[i].start < time)
  257.         {
  258.             time = cl_explosions[i].start;
  259.             index = i;
  260.         }
  261.     memset (&cl_explosions[index], 0, sizeof (cl_explosions[index]));
  262.     return &cl_explosions[index];
  263. }
  264.  
  265. /*
  266. =================
  267. CL_SmokeAndFlash
  268. =================
  269. */
  270. void CL_SmokeAndFlash(vec3_t origin)
  271. {
  272.     explosion_t    *ex;
  273.  
  274. //    ex = CL_AllocExplosion ();
  275. //    VectorCopy (origin, ex->ent.origin);
  276. //    ex->type = ex_misc;
  277. //    ex->frames = 4;
  278. //    ex->ent.flags = RF_TRANSLUCENT;
  279. //    ex->start = cl.frame.servertime - 100;
  280. //    ex->ent.model = cl_mod_smoke;
  281.  
  282.     ex = CL_AllocExplosion ();
  283.     VectorCopy (origin, ex->ent.origin);
  284.     ex->type = ex_flash;
  285.     ex->ent.flags = RF_FULLBRIGHT;
  286.     ex->frames = 2;
  287.     ex->start = cl.frame.servertime - 100;
  288.     ex->ent.model = cl_mod_flash;
  289. }
  290.  
  291. /*
  292. =================
  293. CL_ParseParticles
  294. =================
  295. */
  296. void CL_ParseParticles (void)
  297. {
  298.     int        color, count;
  299.     vec3_t    pos, dir;
  300.  
  301.     MSG_ReadPos (&net_message, pos);
  302.     MSG_ReadDir (&net_message, dir);
  303.  
  304.     color = MSG_ReadByte (&net_message);
  305.  
  306.     count = MSG_ReadByte (&net_message);
  307.  
  308.     CL_ParticleEffect (pos, dir, color, count);
  309. }
  310.  
  311. /*
  312. =================
  313. CL_ParseBeam
  314. =================
  315. */
  316. int CL_ParseBeam (struct model_s *model)
  317. {
  318.     int        ent;
  319.     vec3_t    start, end;
  320.     beam_t    *b;
  321.     int        i;
  322.     
  323.     ent = MSG_ReadShort (&net_message);
  324.     
  325.     MSG_ReadPos (&net_message, start);
  326.     MSG_ReadPos (&net_message, end);
  327.  
  328. // override any beam with the same entity
  329.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  330.         if (b->entity == ent)
  331.         {
  332.             b->entity = ent;
  333.             b->model = model;
  334.             b->endtime = cl.time + 200;
  335.             VectorCopy (start, b->start);
  336.             VectorCopy (end, b->end);
  337.             VectorClear (b->offset);
  338.             return ent;
  339.         }
  340.  
  341. // find a free beam
  342.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  343.     {
  344.         if (!b->model || b->endtime < cl.time)
  345.         {
  346.             b->entity = ent;
  347.             b->model = model;
  348.             b->endtime = cl.time + 200;
  349.             VectorCopy (start, b->start);
  350.             VectorCopy (end, b->end);
  351.             VectorClear (b->offset);
  352.             return ent;
  353.         }
  354.     }
  355.     Com_Printf ("beam list overflow!\n");    
  356.     return ent;
  357. }
  358.  
  359. /*
  360. =================
  361. CL_ParseBeam2
  362. =================
  363. */
  364. int CL_ParseBeam2 (struct model_s *model)
  365. {
  366.     int        ent;
  367.     vec3_t    start, end, offset;
  368.     beam_t    *b;
  369.     int        i;
  370.     
  371.     ent = MSG_ReadShort (&net_message);
  372.     
  373.     MSG_ReadPos (&net_message, start);
  374.     MSG_ReadPos (&net_message, end);
  375.     MSG_ReadPos (&net_message, offset);
  376.  
  377. //    Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
  378.  
  379. // override any beam with the same entity
  380.  
  381.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  382.         if (b->entity == ent)
  383.         {
  384.             b->entity = ent;
  385.             b->model = model;
  386.             b->endtime = cl.time + 200;
  387.             VectorCopy (start, b->start);
  388.             VectorCopy (end, b->end);
  389.             VectorCopy (offset, b->offset);
  390.             return ent;
  391.         }
  392.  
  393. // find a free beam
  394.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  395.     {
  396.         if (!b->model || b->endtime < cl.time)
  397.         {
  398.             b->entity = ent;
  399.             b->model = model;
  400.             b->endtime = cl.time + 200;    
  401.             VectorCopy (start, b->start);
  402.             VectorCopy (end, b->end);
  403.             VectorCopy (offset, b->offset);
  404.             return ent;
  405.         }
  406.     }
  407.     Com_Printf ("beam list overflow!\n");    
  408.     return ent;
  409. }
  410.  
  411. // ROGUE
  412. /*
  413. =================
  414. CL_ParsePlayerBeam
  415.   - adds to the cl_playerbeam array instead of the cl_beams array
  416. =================
  417. */
  418. int CL_ParsePlayerBeam (struct model_s *model)
  419. {
  420.     int        ent;
  421.     vec3_t    start, end, offset;
  422.     beam_t    *b;
  423.     int        i;
  424.     
  425.     ent = MSG_ReadShort (&net_message);
  426.     
  427.     MSG_ReadPos (&net_message, start);
  428.     MSG_ReadPos (&net_message, end);
  429.     // PMM - network optimization
  430.     if (model == cl_mod_heatbeam)
  431.         VectorSet(offset, 2, 7, -3);
  432.     else if (model == cl_mod_monster_heatbeam)
  433.     {
  434.         model = cl_mod_heatbeam;
  435.         VectorSet(offset, 0, 0, 0);
  436.     }
  437.     else
  438.         MSG_ReadPos (&net_message, offset);
  439.  
  440. //    Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
  441.  
  442. // override any beam with the same entity
  443. // PMM - For player beams, we only want one per player (entity) so..
  444.     for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  445.     {
  446.         if (b->entity == ent)
  447.         {
  448.             b->entity = ent;
  449.             b->model = model;
  450.             b->endtime = cl.time + 200;
  451.             VectorCopy (start, b->start);
  452.             VectorCopy (end, b->end);
  453.             VectorCopy (offset, b->offset);
  454.             return ent;
  455.         }
  456.     }
  457.  
  458. // find a free beam
  459.     for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  460.     {
  461.         if (!b->model || b->endtime < cl.time)
  462.         {
  463.             b->entity = ent;
  464.             b->model = model;
  465.             b->endtime = cl.time + 100;        // PMM - this needs to be 100 to prevent multiple heatbeams
  466.             VectorCopy (start, b->start);
  467.             VectorCopy (end, b->end);
  468.             VectorCopy (offset, b->offset);
  469.             return ent;
  470.         }
  471.     }
  472.     Com_Printf ("beam list overflow!\n");    
  473.     return ent;
  474. }
  475. //rogue
  476.  
  477. /*
  478. =================
  479. CL_ParseLightning
  480. =================
  481. */
  482. int CL_ParseLightning (struct model_s *model)
  483. {
  484.     int        srcEnt, destEnt;
  485.     vec3_t    start, end;
  486.     beam_t    *b;
  487.     int        i;
  488.     
  489.     srcEnt = MSG_ReadShort (&net_message);
  490.     destEnt = MSG_ReadShort (&net_message);
  491.  
  492.     MSG_ReadPos (&net_message, start);
  493.     MSG_ReadPos (&net_message, end);
  494.  
  495. // override any beam with the same source AND destination entities
  496.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  497.         if (b->entity == srcEnt && b->dest_entity == destEnt)
  498.         {
  499. //            Com_Printf("%d: OVERRIDE  %d -> %d\n", cl.time, srcEnt, destEnt);
  500.             b->entity = srcEnt;
  501.             b->dest_entity = destEnt;
  502.             b->model = model;
  503.             b->endtime = cl.time + 200;
  504.             VectorCopy (start, b->start);
  505.             VectorCopy (end, b->end);
  506.             VectorClear (b->offset);
  507.             return srcEnt;
  508.         }
  509.  
  510. // find a free beam
  511.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  512.     {
  513.         if (!b->model || b->endtime < cl.time)
  514.         {
  515. //            Com_Printf("%d: NORMAL  %d -> %d\n", cl.time, srcEnt, destEnt);
  516.             b->entity = srcEnt;
  517.             b->dest_entity = destEnt;
  518.             b->model = model;
  519.             b->endtime = cl.time + 200;
  520.             VectorCopy (start, b->start);
  521.             VectorCopy (end, b->end);
  522.             VectorClear (b->offset);
  523.             return srcEnt;
  524.         }
  525.     }
  526.     Com_Printf ("beam list overflow!\n");    
  527.     return srcEnt;
  528. }
  529.  
  530. /*
  531. =================
  532. CL_ParseLaser
  533. =================
  534. */
  535. void CL_ParseLaser (int colors)
  536. {
  537.     vec3_t    start;
  538.     vec3_t    end;
  539.     laser_t    *l;
  540.     int        i;
  541.  
  542.     MSG_ReadPos (&net_message, start);
  543.     MSG_ReadPos (&net_message, end);
  544.  
  545.     for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
  546.     {
  547.         if (l->endtime < cl.time)
  548.         {
  549.             l->ent.flags = RF_TRANSLUCENT | RF_BEAM;
  550.             VectorCopy (start, l->ent.origin);
  551.             VectorCopy (end, l->ent.oldorigin);
  552.             l->ent.alpha = 0.30;
  553.             l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff;
  554.             l->ent.model = NULL;
  555.             l->ent.frame = 4;
  556.             l->endtime = cl.time + 100;
  557.             return;
  558.         }
  559.     }
  560. }
  561.  
  562. //=============
  563. //ROGUE
  564. void CL_ParseSteam (void)
  565. {
  566.     vec3_t    pos, dir;
  567.     int        id, i;
  568.     int        r;
  569.     int        cnt;
  570.     int        color;
  571.     int        magnitude;
  572.     cl_sustain_t    *s, *free_sustain;
  573.  
  574. //    id = MSG_ReadShort (&net_message);        // an id of -1 is an instant effect
  575.     id = 25;
  576.     if (id != -1) // sustains
  577.     {
  578. //            Com_Printf ("Sustain effect id %d\n", id);
  579.         free_sustain = NULL;
  580.         for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  581.         {
  582.             if (s->id == 0)
  583.             {
  584.                 free_sustain = s;
  585.                 break;
  586.             }
  587.         }
  588.         if (free_sustain)
  589.         {
  590.             s->id = id;
  591.             s->count = MSG_ReadByte (&net_message);
  592.             s->count = 10;//just for testing here
  593.             MSG_ReadPos (&net_message, s->org);
  594.             MSG_ReadDir (&net_message, s->dir);
  595.             r = MSG_ReadByte (&net_message);
  596.             s->color = r & 0xff;
  597.             s->magnitude = 50;//MSG_ReadShort (&net_message);
  598.             s->endtime = cl.time + 10000000;//MSG_ReadLong (&net_message);
  599.             s->think = CL_ParticleSteamEffect2;
  600.             s->thinkinterval = 1;
  601.             s->nextthink = cl.time;
  602.         }
  603.         else
  604.         {
  605. //                Com_Printf ("No free sustains!\n");
  606.             // FIXME - read the stuff anyway
  607.             cnt = MSG_ReadByte (&net_message);
  608.             MSG_ReadPos (&net_message, pos);
  609.             MSG_ReadDir (&net_message, dir);
  610.             r = MSG_ReadByte (&net_message);
  611.             magnitude = MSG_ReadShort (&net_message);
  612.             magnitude = MSG_ReadLong (&net_message); // really interval
  613.         }
  614.     }
  615.     else // instant
  616.     {
  617.         cnt = MSG_ReadByte (&net_message);
  618.         MSG_ReadPos (&net_message, pos);
  619.         MSG_ReadDir (&net_message, dir);
  620.         r = MSG_ReadByte (&net_message);
  621.         magnitude = MSG_ReadShort (&net_message);
  622.         color = r & 0xff;
  623.         CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  624. //        S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  625.     }
  626. }
  627.  
  628. void CL_ParseFire (void)
  629. {
  630.     vec3_t    pos, dir;
  631.     int        id, i;
  632.     int        r;
  633.     int        cnt;
  634.     int        magnitude;
  635.     cl_sustain_t    *s, *free_sustain;
  636.  
  637. //    id = MSG_ReadShort (&net_message);        // an id of -1 is an instant effect
  638.     id = 25;
  639.     if (id != -1) // sustains
  640.     {
  641. //            Com_Printf ("Sustain effect id %d\n", id);
  642.         free_sustain = NULL;
  643.         for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  644.         {
  645.             if (s->id == 0)
  646.             {
  647.                 free_sustain = s;
  648.                 break;
  649.             }
  650.         }
  651.         if (free_sustain)
  652.         {
  653.             s->id = id;
  654.             s->count = MSG_ReadByte (&net_message);
  655.             s->count = 10;//just for testing here
  656.             MSG_ReadPos (&net_message, s->org);
  657.             MSG_ReadDir (&net_message, s->dir);
  658.             r = MSG_ReadByte (&net_message);
  659.             s->color = r & 0xff;
  660.             s->magnitude = 150;//MSG_ReadShort (&net_message);
  661.             s->endtime = cl.time + 10000000;//MSG_ReadLong (&net_message);
  662.             s->think = CL_ParticleFireEffect2;
  663.             s->thinkinterval = 1;
  664.             s->nextthink = cl.time;
  665.         }
  666.         else
  667.         {
  668. //                Com_Printf ("No free sustains!\n");
  669.             // FIXME - read the stuff anyway
  670.             cnt = MSG_ReadByte (&net_message);
  671.             MSG_ReadPos (&net_message, pos);
  672.             MSG_ReadDir (&net_message, dir);
  673.             r = MSG_ReadByte (&net_message);
  674.             magnitude = MSG_ReadShort (&net_message);
  675.             magnitude = MSG_ReadLong (&net_message); // really interval
  676.         }
  677.     }
  678.     
  679. }
  680.  
  681. void CL_ParseSmoke (void)
  682. {
  683.     vec3_t    pos, dir;
  684.     int        id, i;
  685.     int        r;
  686.     int        cnt;
  687.     int        magnitude;
  688.     cl_sustain_t    *s, *free_sustain;
  689.  
  690. //    id = MSG_ReadShort (&net_message);        // an id of -1 is an instant effect
  691.     id = 25;
  692.     if (id != -1) // sustains
  693.     {
  694. //            Com_Printf ("Sustain effect id %d\n", id);
  695.         free_sustain = NULL;
  696.         for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  697.         {
  698.             if (s->id == 0)
  699.             {
  700.                 free_sustain = s;
  701.                 break;
  702.             }
  703.         }
  704.         if (free_sustain)
  705.         {
  706.             s->id = id;
  707.             s->count = MSG_ReadByte (&net_message);
  708.             s->count = 40;//just for testing here
  709.             MSG_ReadPos (&net_message, s->org);
  710.             MSG_ReadDir (&net_message, s->dir);
  711.             r = MSG_ReadByte (&net_message);
  712.             s->color = r & 0xff;
  713.             s->magnitude = 400;//MSG_ReadShort (&net_message);
  714.             s->endtime = cl.time + 10000000;//MSG_ReadLong (&net_message);
  715.             s->think = CL_ParticleSmokeEffect2;
  716.             s->thinkinterval = 1;
  717.             s->nextthink = cl.time;
  718.         }
  719.         else
  720.         {
  721. //                Com_Printf ("No free sustains!\n");
  722.             // FIXME - read the stuff anyway
  723.             cnt = MSG_ReadByte (&net_message);
  724.             MSG_ReadPos (&net_message, pos);
  725.             MSG_ReadDir (&net_message, dir);
  726.             r = MSG_ReadByte (&net_message);
  727.             magnitude = MSG_ReadShort (&net_message);
  728.             magnitude = MSG_ReadLong (&net_message); // really interval
  729.         }
  730.     }
  731.     
  732. }
  733. void CL_ParseWidow (void)
  734. {
  735.     vec3_t    pos;
  736.     int        id, i;
  737.     cl_sustain_t    *s, *free_sustain;
  738.  
  739.     id = MSG_ReadShort (&net_message);
  740.  
  741.     free_sustain = NULL;
  742.     for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  743.     {
  744.         if (s->id == 0)
  745.         {
  746.             free_sustain = s;
  747.             break;
  748.         }
  749.     }
  750.     if (free_sustain)
  751.     {
  752.         s->id = id;
  753.         MSG_ReadPos (&net_message, s->org);
  754.         s->endtime = cl.time + 2100;
  755.         s->think = CL_Widowbeamout;
  756.         s->thinkinterval = 1;
  757.         s->nextthink = cl.time;
  758.     }
  759.     else // no free sustains
  760.     {
  761.         // FIXME - read the stuff anyway
  762.         MSG_ReadPos (&net_message, pos);
  763.     }
  764. }
  765.  
  766. void CL_ParseNuke (void)
  767. {
  768.     vec3_t    pos;
  769.     int        i;
  770.     cl_sustain_t    *s, *free_sustain;
  771.  
  772.     free_sustain = NULL;
  773.     for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  774.     {
  775.         if (s->id == 0)
  776.         {
  777.             free_sustain = s;
  778.             break;
  779.         }
  780.     }
  781.     if (free_sustain)
  782.     {
  783.         s->id = 21000;
  784.         MSG_ReadPos (&net_message, s->org);
  785.         s->endtime = cl.time + 1000;
  786.         s->think = CL_Nukeblast;
  787.         s->thinkinterval = 1;
  788.         s->nextthink = cl.time;
  789.     }
  790.     else // no free sustains
  791.     {
  792.         // FIXME - read the stuff anyway
  793.         MSG_ReadPos (&net_message, pos);
  794.     }
  795. }
  796.  
  797. //ROGUE
  798. //=============
  799.  
  800.  
  801. /*
  802. =================
  803. CL_ParseTEnt
  804. =================
  805. */
  806. static byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
  807.  
  808. void CL_ParseTEnt (void)
  809. {
  810.     int        type;
  811.     vec3_t    pos, pos2, dir;
  812.     explosion_t    *ex;
  813.     int        cnt;
  814.     int        color;
  815.     int        r;
  816.     int        ent;
  817.     int        magnitude;
  818.     float    fcolor[3], intensity, alpha;
  819.  
  820.     type = MSG_ReadByte (&net_message);
  821.  
  822.     switch (type)
  823.     {
  824.     case TE_BLOOD:            // bullet hitting flesh
  825.         MSG_ReadPos (&net_message, pos);
  826.         MSG_ReadDir (&net_message, dir);
  827.         CL_ParticleEffect (pos, dir, 450, 60);// doing the blood here - color is red
  828.         break;
  829.     case TE_GREENBLOOD:
  830.         MSG_ReadPos (&net_message, pos);
  831.         MSG_ReadDir (&net_message, dir);
  832.         CL_ParticleEffect (pos, dir, 550, 60);// doing the blood here - color is green
  833.         break;
  834.     case TE_GUNSHOT:
  835.     case TE_SPARKS:
  836.     case TE_BULLET_SPARKS:
  837.         MSG_ReadPos (&net_message, pos);
  838.         MSG_ReadDir (&net_message, dir);
  839.  
  840.         // FIXME: change to type
  841.         if (type == TE_GUNSHOT)
  842.             CL_ParticleEffect (pos, dir, 425, 10);    // shotgun - do I use this?
  843.         else
  844.             CL_ParticleEffect (pos, dir, 425, 2);    // bullets, color is 0xe0
  845.  
  846.         if (type != TE_SPARKS)
  847.         {
  848.         //    CL_SmokeAndFlash(pos);
  849.             
  850.             // impact sound
  851.             cnt = rand()&15;
  852.             if (cnt == 1)
  853.                 S_StartSound (pos, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0);
  854.             else if (cnt == 2)
  855.                 S_StartSound (pos, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0);
  856.             else if (cnt == 3)
  857.                 S_StartSound (pos, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0);
  858.         }
  859.  
  860.         break;
  861.         
  862.     case TE_SCREEN_SPARKS:
  863.     case TE_SHIELD_SPARKS:
  864.         MSG_ReadPos (&net_message, pos);
  865.         MSG_ReadDir (&net_message, dir);
  866.         if (type == TE_SCREEN_SPARKS)
  867.             CL_ParticleEffect (pos, dir, 0xd0, 40);
  868.         else
  869.             CL_ParticleEffect (pos, dir, 0xb0, 40);
  870.         //FIXME : replace or remove this sound
  871.         S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  872.         break;
  873.         
  874.     case TE_SHOTGUN:                // martian laser effect
  875.         MSG_ReadPos (&net_message, pos);
  876.         MSG_ReadPos (&net_message, pos2);
  877.         CL_LaserTrail (pos, pos2);
  878.         break;
  879.  
  880.     case TE_SPLASH:            // bullet hitting water
  881.         cnt = MSG_ReadByte (&net_message);
  882.         MSG_ReadPos (&net_message, pos);
  883.         MSG_ReadDir (&net_message, dir);
  884.         r = MSG_ReadByte (&net_message);
  885.         if (r > 6)
  886.             color = 0x00;
  887.         else
  888.             color = splash_color[r];
  889.         CL_ParticleEffect (pos, dir, color, cnt);
  890.  
  891.         if (r == SPLASH_SPARKS)
  892.         {
  893.             r = rand() & 3;
  894.             if (r == 0)
  895.                 S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0);
  896.             else if (r == 1)
  897.                 S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0);
  898.             else
  899.                 S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0);
  900.         }
  901.         break;
  902.  
  903.     case TE_LASER_SPARKS:
  904.         cnt = MSG_ReadByte (&net_message);
  905.         MSG_ReadPos (&net_message, pos);
  906.         MSG_ReadDir (&net_message, dir);
  907.         color = MSG_ReadByte (&net_message);
  908.         CL_ParticleEffect2 (pos, dir, color, cnt);
  909.         break;
  910.  
  911.     // RAFAEL
  912.     case TE_BLUEHYPERBLASTER:
  913.         MSG_ReadPos (&net_message, pos);
  914.         MSG_ReadPos (&net_message, dir);
  915.         CL_BlasterParticles (pos, dir);
  916.         break;
  917.  
  918.     case TE_BLASTER:            // blaster hitting wall
  919.         MSG_ReadPos (&net_message, pos);
  920.         MSG_ReadDir (&net_message, dir);
  921.         CL_BlasterParticles (pos, dir);
  922.  
  923. /*        ex = CL_AllocExplosion ();
  924.         VectorCopy (pos, ex->ent.origin);
  925.         ex->ent.angles[0] = acos(dir[2])/M_PI*180;
  926.     // PMM - fixed to correct for pitch of 0
  927.         if (dir[0])
  928.             ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
  929.         else if (dir[1] > 0)
  930.             ex->ent.angles[1] = 90;
  931.         else if (dir[1] < 0)
  932.             ex->ent.angles[1] = 270;
  933.         else
  934.             ex->ent.angles[1] = 0;
  935.  
  936.         ex->type = ex_misc;
  937.         ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  938.         ex->start = cl.frame.servertime - 100;
  939.         ex->light = 150;
  940.         ex->lightcolor[0] = 1;
  941.         ex->lightcolor[1] = 1;
  942.         ex->ent.model = cl_mod_explode;
  943.         ex->frames = 4;
  944.         
  945.         S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); */
  946.         break;
  947.         
  948.     case TE_RAILTRAIL:            // railgun effect - let's try the heat missile thingy too!
  949.         MSG_ReadPos (&net_message, pos);
  950.         MSG_ReadPos (&net_message, pos2);
  951.         CL_RailTrail (pos, pos2);
  952.         //CL_Heatbeam (pos, pos2);
  953.         S_StartSound (pos, 0, 0, cl_sfx_railg, 1, ATTN_NONE, 0);
  954.         break;
  955.  
  956.     case TE_EXPLOSION2: //using this for a "dust" explosion, ie big, big footsteps effect
  957.         MSG_ReadPos (&net_message, pos);
  958.  
  959.         ex = CL_AllocExplosion ();
  960.         VectorCopy (pos, ex->ent.origin);
  961.         ex->start = cl.frame.servertime - 100;
  962.         
  963.         ex->ent.angles[1] = rand() % 360;
  964.     
  965.         
  966.         CL_DustParticles (pos);                                    
  967.         break;
  968.  
  969.     case TE_GRENADE_EXPLOSION:
  970.     case TE_GRENADE_EXPLOSION_WATER:
  971.         MSG_ReadPos (&net_message, pos);
  972.  
  973.         ex = CL_AllocExplosion ();
  974.         VectorCopy (pos, ex->ent.origin);
  975.         ex->type = ex_poly;
  976.         ex->ent.flags = RF_FULLBRIGHT;
  977.         ex->start = cl.frame.servertime - 100;
  978.         ex->light = 350;
  979.         ex->lightcolor[0] = 1.0;
  980.         ex->lightcolor[1] = 0.5;
  981.         ex->lightcolor[2] = 0.5;
  982.         ex->ent.model = cl_mod_explo4;
  983.         ex->frames = 19;
  984.         ex->baseframe = 30;
  985.         ex->ent.angles[1] = rand() % 360;
  986.         CL_ExplosionParticles (pos);
  987.         if (type == TE_GRENADE_EXPLOSION_WATER)
  988.             S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  989.         else
  990.             S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
  991.  
  992.         V_AddStain ( pos, 17, 15, 15, 15, 200 );
  993.  
  994.         break;
  995.  
  996.     // RAFAEL
  997.     case TE_PLASMA_EXPLOSION:
  998.         MSG_ReadPos (&net_message, pos);
  999.         ex = CL_AllocExplosion ();
  1000.         VectorCopy (pos, ex->ent.origin);
  1001.         ex->type = ex_poly;
  1002.         ex->ent.flags = RF_FULLBRIGHT;
  1003.         ex->start = cl.frame.servertime - 100;
  1004.         ex->light = 350;
  1005.         ex->lightcolor[0] = 1.0; 
  1006.         ex->lightcolor[1] = 0.5;
  1007.         ex->lightcolor[2] = 0.5;
  1008.         ex->ent.angles[1] = rand() % 360;
  1009.         ex->ent.model = cl_mod_explo4;
  1010.         if (frand() < 0.5)
  1011.             ex->baseframe = 15;
  1012.         ex->frames = 15;
  1013.         CL_ExplosionParticles (pos);
  1014.         S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  1015.         break;
  1016.     
  1017.     case TE_EXPLOSION1:
  1018.     case TE_EXPLOSION1_BIG:                        // PMM
  1019.     case TE_ROCKET_EXPLOSION:
  1020.     case TE_ROCKET_EXPLOSION_WATER:
  1021.     case TE_EXPLOSION1_NP:                        // PMM
  1022.         MSG_ReadPos (&net_message, pos);
  1023.  
  1024.         ex = CL_AllocExplosion ();
  1025.         VectorCopy (pos, ex->ent.origin);
  1026. //        ex->type = ex_poly;
  1027.         ex->ent.flags = RF_FULLBRIGHT;
  1028.         ex->start = cl.frame.servertime - 100;
  1029.         ex->light = 350;
  1030.         ex->lightcolor[0] = 1.0;
  1031.         ex->lightcolor[1] = 0.5;
  1032.         ex->lightcolor[2] = 0.5;
  1033.         ex->ent.angles[1] = rand() % 360;
  1034.  
  1035.         V_AddStain ( pos, 25, 15, 15, 15, 200 );
  1036.         V_AddStain ( pos, 25*3, 15, 15, 15, 66 );
  1037.     
  1038.         if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP))        // PMM
  1039.             CL_ExplosionParticles (pos);                                    // PMM
  1040.         if (type == TE_ROCKET_EXPLOSION_WATER)
  1041.             S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  1042.         else
  1043.             S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  1044.  
  1045.         break;
  1046.  
  1047.     case TE_BFG_EXPLOSION:
  1048.         MSG_ReadPos (&net_message, pos);
  1049.         ex = CL_AllocExplosion ();
  1050.         VectorCopy (pos, ex->ent.origin);
  1051.         ex->type = ex_poly;
  1052.         ex->ent.flags = RF_FULLBRIGHT;
  1053.         ex->start = cl.frame.servertime - 100;
  1054.         ex->light = 350;
  1055.         ex->lightcolor[0] = 0.0;
  1056.         ex->lightcolor[1] = 1.0;
  1057.         ex->lightcolor[2] = 0.0;
  1058.         ex->ent.model = cl_mod_bfg_explo;
  1059.         ex->ent.flags |= RF_TRANSLUCENT;
  1060.         ex->ent.alpha = 0.30;
  1061.         ex->frames = 4;
  1062.         break;
  1063.  
  1064.     case TE_BFG_BIGEXPLOSION:
  1065.         MSG_ReadPos (&net_message, pos);
  1066.         CL_BFGExplosionParticles (pos);
  1067.         break;
  1068.  
  1069.     case TE_BFG_LASER:
  1070.         CL_ParseLaser (0xd0d1d2d3);
  1071.         break;
  1072.  
  1073.     case TE_BUBBLETRAIL:
  1074.         //MSG_ReadPos (&net_message, pos);
  1075.         //MSG_ReadPos (&net_message, pos2);
  1076.         //CL_BubbleTrail (pos, pos2);
  1077.         //break;
  1078.         MSG_ReadPos (&net_message, pos);
  1079.         MSG_ReadPos (&net_message, pos2);
  1080.         CL_RailTrail (pos, pos2);
  1081.         break;
  1082.  
  1083.     case TE_PARASITE_ATTACK:
  1084.         MSG_ReadPos (&net_message, pos);
  1085.         MSG_ReadPos (&net_message, pos2);
  1086.         CL_LaserBlast (pos, pos2);
  1087.         S_StartSound (pos, 0, 0, S_RegisterSound ("weapons/biglaser.wav"), 1, ATTN_NONE, 0);
  1088.         break;
  1089.  
  1090.     case TE_MEDIC_CABLE_ATTACK:
  1091.         MSG_ReadPos (&net_message, pos);
  1092.         MSG_ReadPos (&net_message, pos2);
  1093.         CL_HeatBlast (pos, pos2);
  1094.         break;
  1095.  
  1096.     case TE_BOSSTPORT:            // boss teleporting to station
  1097.         MSG_ReadPos (&net_message, pos);
  1098.         CL_BigTeleportParticles (pos);
  1099.         S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0);
  1100.         break;
  1101.  
  1102.     case TE_GRAPPLE_CABLE:
  1103.         ent = CL_ParseBeam2 (cl_mod_grapple_cable);
  1104.         break;
  1105.  
  1106.     // RAFAEL
  1107.     case TE_WELDING_SPARKS:
  1108.         cnt = MSG_ReadByte (&net_message);
  1109.         MSG_ReadPos (&net_message, pos);
  1110.         MSG_ReadDir (&net_message, dir);
  1111.         color = MSG_ReadByte (&net_message);
  1112.         CL_ParticleEffect2 (pos, dir, color, cnt);
  1113.  
  1114.         ex = CL_AllocExplosion ();
  1115.         VectorCopy (pos, ex->ent.origin);
  1116.         ex->type = ex_flash;
  1117.         // note to self
  1118.         // we need a better no draw flag
  1119.         ex->ent.flags = RF_BEAM;
  1120.         ex->start = cl.frame.servertime - 0.1;
  1121.         ex->light = 100 + (rand()%75);
  1122.         ex->lightcolor[0] = 1.0;
  1123.         ex->lightcolor[1] = 1.0;
  1124.         ex->lightcolor[2] = 0.3;
  1125.         ex->ent.model = cl_mod_flash;
  1126.         ex->frames = 2;
  1127.         break;
  1128.  
  1129.     // RAFAEL
  1130.     case TE_TUNNEL_SPARKS:
  1131.         cnt = MSG_ReadByte (&net_message);
  1132.         MSG_ReadPos (&net_message, pos);
  1133.         MSG_ReadDir (&net_message, dir);
  1134.         color = MSG_ReadByte (&net_message);
  1135.         CL_ParticleEffect3 (pos, dir, color, cnt);
  1136.         break;
  1137.  
  1138. //=============
  1139. //PGM
  1140.         // PMM -following code integrated for flechette (different color)
  1141.     case TE_BLASTER2:            // green blaster hitting wall
  1142.     case TE_FLECHETTE:            // flechette
  1143.         MSG_ReadPos (&net_message, pos);
  1144.         MSG_ReadDir (&net_message, dir);
  1145.         
  1146.         // PMM
  1147.         if (type == TE_BLASTER2)
  1148.             CL_BlasterParticles2 (pos, dir, 0xd0);
  1149.         else
  1150.             CL_BlasterParticles2 (pos, dir, 0x6f); // 75
  1151.  
  1152.         ex = CL_AllocExplosion ();
  1153.         VectorCopy (pos, ex->ent.origin);
  1154.         ex->ent.angles[0] = acos(dir[2])/M_PI*180;
  1155.     // PMM - fixed to correct for pitch of 0
  1156.         if (dir[0])
  1157.             ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
  1158.         else if (dir[1] > 0)
  1159.             ex->ent.angles[1] = 90;
  1160.         else if (dir[1] < 0)
  1161.             ex->ent.angles[1] = 270;
  1162.         else
  1163.             ex->ent.angles[1] = 0;
  1164.  
  1165.         ex->type = ex_misc;
  1166.         ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  1167.  
  1168.         // PMM
  1169.         if (type == TE_BLASTER2)
  1170.             ex->ent.skinnum = 1;
  1171.         else // flechette
  1172.             ex->ent.skinnum = 2;
  1173.  
  1174.         ex->start = cl.frame.servertime - 100;
  1175.         ex->light = 150;
  1176.         // PMM
  1177.         if (type == TE_BLASTER2)
  1178.             ex->lightcolor[1] = 1;
  1179.         else // flechette
  1180.         {
  1181.             ex->lightcolor[0] = 0.19;
  1182.             ex->lightcolor[1] = 0.41;
  1183.             ex->lightcolor[2] = 0.75;
  1184.         }
  1185.         ex->ent.model = cl_mod_explode;
  1186.         ex->frames = 4;
  1187.         S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1188.         break;
  1189.  
  1190.  
  1191.     case TE_LIGHTNING:
  1192.         //screw this crappy old shit!!
  1193.     //    ent = CL_ParseLightning (cl_mod_lightning);
  1194.     //    S_StartSound (NULL, ent, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0);
  1195.         MSG_ReadPos (&net_message, pos);
  1196.         MSG_ReadPos (&net_message, pos2);
  1197.         CL_NewLightning (pos, pos2);
  1198.         break;
  1199.  
  1200.     case TE_DEBUGTRAIL:
  1201.         MSG_ReadPos (&net_message, pos);
  1202.         MSG_ReadPos (&net_message, pos2);
  1203.         CL_DebugTrail (pos, pos2);
  1204.         break;
  1205.  
  1206.     case TE_PLAIN_EXPLOSION:
  1207.         MSG_ReadPos (&net_message, pos);
  1208.  
  1209.         ex = CL_AllocExplosion ();
  1210.         VectorCopy (pos, ex->ent.origin);
  1211.         ex->type = ex_poly;
  1212.         ex->ent.flags = RF_FULLBRIGHT;
  1213.         ex->start = cl.frame.servertime - 100;
  1214.         ex->light = 350;
  1215.         ex->lightcolor[0] = 1.0;
  1216.         ex->lightcolor[1] = 0.5;
  1217.         ex->lightcolor[2] = 0.5;
  1218.         ex->ent.angles[1] = rand() % 360;
  1219.         ex->ent.model = cl_mod_explo4;
  1220.         if (frand() < 0.5)
  1221.             ex->baseframe = 15;
  1222.         ex->frames = 15;
  1223.         if (type == TE_ROCKET_EXPLOSION_WATER)
  1224.             S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  1225.         else
  1226.             S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  1227.         break;
  1228.  
  1229.     case TE_FLASHLIGHT:
  1230.         MSG_ReadPos(&net_message, pos);
  1231.         ent = MSG_ReadShort(&net_message);
  1232.         CL_Flashlight(ent, pos);
  1233.         break;
  1234.  
  1235.     case TE_FORCEWALL:
  1236.         MSG_ReadPos(&net_message, pos);
  1237.         MSG_ReadPos(&net_message, pos2);
  1238.         color = MSG_ReadByte (&net_message);
  1239.         CL_ForceWall(pos, pos2, color);
  1240.         break;
  1241.  
  1242.     case TE_HEATBEAM:
  1243.         //ent = CL_ParsePlayerBeam (cl_mod_heatbeam);
  1244.         MSG_ReadPos (&net_message, pos);
  1245.         MSG_ReadPos (&net_message, pos2);
  1246.         CL_Heatbeam (pos, pos2);
  1247.         break;
  1248.  
  1249.     case TE_MONSTER_HEATBEAM:
  1250.         ent = CL_ParsePlayerBeam (cl_mod_monster_heatbeam);
  1251.         break;
  1252.  
  1253.     case TE_HEATBEAM_SPARKS:
  1254. //        cnt = MSG_ReadByte (&net_message);
  1255.         cnt = 50;
  1256.         MSG_ReadPos (&net_message, pos);
  1257.         MSG_ReadDir (&net_message, dir);
  1258. //        r = MSG_ReadByte (&net_message);
  1259. //        magnitude = MSG_ReadShort (&net_message);
  1260.         r = 8;
  1261.         magnitude = 60;
  1262.         color = r & 0xff;
  1263.         CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  1264.         S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1265.         break;
  1266.     
  1267.     case TE_HEATBEAM_STEAM:
  1268. //        cnt = MSG_ReadByte (&net_message);
  1269.         cnt = 20;
  1270.         MSG_ReadPos (&net_message, pos);
  1271.         MSG_ReadDir (&net_message, dir);
  1272. //        r = MSG_ReadByte (&net_message);
  1273. //        magnitude = MSG_ReadShort (&net_message);
  1274. //        color = r & 0xff;
  1275.         color = 0xe0;
  1276.         magnitude = 60;
  1277.         CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  1278.         S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1279.         break;
  1280.  
  1281.     case TE_STEAM:
  1282.         CL_ParseSteam();
  1283.         break;
  1284.     case TE_FIRE:
  1285.         CL_ParseFire();
  1286.         break;
  1287.     case TE_SMOKE:
  1288.         CL_ParseSmoke();
  1289.         break;
  1290.     case TE_BUBBLETRAIL2:
  1291. //        cnt = MSG_ReadByte (&net_message);
  1292.         cnt = 8;
  1293.         MSG_ReadPos (&net_message, pos);
  1294.         MSG_ReadPos (&net_message, pos2);
  1295.         CL_BubbleTrail2 (pos, pos2, cnt);
  1296.         S_StartSound (pos,  0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1297.         break;
  1298.  
  1299.     case TE_MOREBLOOD:
  1300.         MSG_ReadPos (&net_message, pos);
  1301.         MSG_ReadDir (&net_message, dir);
  1302.         CL_ParticleEffect (pos, dir, 0xe8, 250);
  1303.         break;
  1304.  
  1305.     case TE_CHAINFIST_SMOKE:
  1306.         dir[0]=0; dir[1]=0; dir[2]=1;
  1307.         MSG_ReadPos(&net_message, pos);
  1308.         CL_ParticleSmokeEffect (pos, dir, 0, 20, 20);
  1309.         break;
  1310.  
  1311.     case TE_ELECTRIC_SPARKS:
  1312.         MSG_ReadPos (&net_message, pos);
  1313.         MSG_ReadDir (&net_message, dir);
  1314. //        CL_ParticleEffect (pos, dir, 109, 40);
  1315.         CL_ParticleEffect (pos, dir, 0x75, 40);
  1316.         //FIXME : replace or remove this sound
  1317.         S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1318.         break;
  1319.  
  1320.     case TE_TRACKER_EXPLOSION:
  1321.         MSG_ReadPos (&net_message, pos);
  1322.         CL_ColorFlash (pos, 0, 150, -1, -1, -1);
  1323.         CL_ColorExplosionParticles (pos, 0, 1);
  1324. //        CL_Tracker_Explode (pos);
  1325.         S_StartSound (pos, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0);
  1326.         break;
  1327.  
  1328.     case TE_TELEPORT_EFFECT:
  1329.     case TE_DBALL_GOAL:
  1330.         MSG_ReadPos (&net_message, pos);
  1331.         CL_TeleportParticles (pos);
  1332.         break;
  1333.  
  1334.     case TE_WIDOWBEAMOUT:
  1335.         CL_ParseWidow ();
  1336.         break;
  1337.  
  1338.     case TE_NUKEBLAST:
  1339.         CL_ParseNuke ();
  1340.         break;
  1341.  
  1342.     case TE_WIDOWSPLASH:
  1343.         MSG_ReadPos (&net_message, pos);
  1344.         CL_WidowSplash (pos);
  1345.         break;
  1346. //PGM
  1347. //==============
  1348.  
  1349.     case TE_LEADERBLASTER:
  1350.         MSG_ReadPos (&net_message, pos);
  1351.         MSG_ReadPos (&net_message, pos2);
  1352.         CL_LaserBlast2 (pos, pos2);
  1353.         S_StartSound (pos, 0, 0, S_RegisterSound ("weapons/biglaser.wav"), 1, ATTN_NONE, 0);
  1354.         break;
  1355.  
  1356.     case TE_BLASTER_MUZZLEFLASH:
  1357.         MSG_ReadPos (&net_message, pos);
  1358.         ex = CL_AllocExplosion ();
  1359.         VectorCopy (pos, ex->ent.origin);
  1360.         ex->ent.flags = RF_FULLBRIGHT;
  1361.         ex->start = cl.frame.servertime - 100;
  1362.         ex->light = 350;
  1363.         ex->lightcolor[0] = 1.0;
  1364.         ex->lightcolor[1] = 0.5;
  1365.         ex->lightcolor[2] = 0.0;
  1366.         CL_MuzzleParticles (pos);
  1367.         break;
  1368.  
  1369.     case TE_SMART_MUZZLEFLASH:
  1370.         MSG_ReadPos (&net_message, pos);
  1371.         ex = CL_AllocExplosion ();
  1372.         VectorCopy (pos, ex->ent.origin);
  1373.         ex->ent.flags = RF_FULLBRIGHT;
  1374.         ex->start = cl.frame.servertime - 100;
  1375.         ex->light = 350;
  1376.         ex->lightcolor[0] = 1.0;
  1377.         ex->lightcolor[1] = 0.0;
  1378.         ex->lightcolor[2] = 1.0;
  1379.         CL_Leaderfield (pos);
  1380.         break;
  1381.  
  1382.     case TE_LEADERFIELD:
  1383.         MSG_ReadPos (&net_message, pos);
  1384.         MSG_ReadDir (&net_message, dir);
  1385.         CL_Leaderfield (pos);
  1386.         ex = CL_AllocExplosion ();
  1387.         ex->ent.flags = RF_FULLBRIGHT;
  1388.         ex->light = 350;
  1389.         ex->lightcolor[0] = 1.0;
  1390.         ex->lightcolor[1] = 0.0;
  1391.         ex->lightcolor[2] = 1.0;
  1392.         break;
  1393.  
  1394.     case TE_BLASTERBEAM:            // blaster beam effect
  1395.         MSG_ReadPos (&net_message, pos);
  1396.         MSG_ReadPos (&net_message, pos2);
  1397.         CL_BlasterBeamTrail (pos, pos2);
  1398.         break;
  1399.  
  1400.     case TE_STAIN:
  1401.         MSG_ReadPos (&net_message, pos);
  1402.         intensity = MSG_ReadFloat (&net_message);
  1403.         fcolor[0] = MSG_ReadByte (&net_message);
  1404.         fcolor[1] = MSG_ReadByte (&net_message);
  1405.         fcolor[2] = MSG_ReadByte (&net_message);
  1406.         alpha = MSG_ReadByte (&net_message);
  1407.         V_AddStain ( pos, intensity, fcolor[0], fcolor[1], fcolor[2], alpha );
  1408.         break;
  1409.  
  1410.     default:
  1411.         Com_Error (ERR_DROP, "CL_ParseTEnt: bad type");
  1412.     }
  1413. }
  1414.  
  1415. /*
  1416. =================
  1417. CL_AddBeams
  1418. =================
  1419. */
  1420. void CL_AddBeams (void)
  1421. {
  1422.     int            i,j;
  1423.     beam_t        *b;
  1424.     vec3_t        dist, org;
  1425.     float        d;
  1426.     entity_t    ent;
  1427.     float        yaw, pitch;
  1428.     float        forward;
  1429.     float        len, steps;
  1430.     float        model_length;
  1431.     
  1432. // update beams
  1433.     for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  1434.     {
  1435.         if (!b->model || b->endtime < cl.time)
  1436.             continue;
  1437.  
  1438.         // if coming from the player, update the start position
  1439.         if (b->entity == cl.playernum+1)    // entity 0 is the world
  1440.         {
  1441.             VectorCopy (cl.refdef.vieworg, b->start);
  1442.             b->start[2] -= 22;    // adjust for view height
  1443.         }
  1444.         VectorAdd (b->start, b->offset, org);
  1445.  
  1446.     // calculate pitch and yaw
  1447.         VectorSubtract (b->end, org, dist);
  1448.  
  1449.         if (dist[1] == 0 && dist[0] == 0)
  1450.         {
  1451.             yaw = 0;
  1452.             if (dist[2] > 0)
  1453.                 pitch = 90;
  1454.             else
  1455.                 pitch = 270;
  1456.         }
  1457.         else
  1458.         {
  1459.     // PMM - fixed to correct for pitch of 0
  1460.             if (dist[0])
  1461.                 yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
  1462.             else if (dist[1] > 0)
  1463.                 yaw = 90;
  1464.             else
  1465.                 yaw = 270;
  1466.             if (yaw < 0)
  1467.                 yaw += 360;
  1468.     
  1469.             forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  1470.             pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
  1471.             if (pitch < 0)
  1472.                 pitch += 360.0;
  1473.         }
  1474.  
  1475.     // add new entities for the beams
  1476.         d = VectorNormalize(dist);
  1477.  
  1478.         memset (&ent, 0, sizeof(ent));
  1479.         if (b->model == cl_mod_lightning)
  1480.         {
  1481.             model_length = 35.0;
  1482.             d-= 20.0;  // correction so it doesn't end in middle of tesla
  1483.         }
  1484.         else
  1485.         {
  1486.             model_length = 30.0;
  1487.         }
  1488.         steps = ceil(d/model_length);
  1489.         len = (d-model_length)/(steps-1);
  1490.  
  1491.         // PMM - special case for lightning model .. if the real length is shorter than the model,
  1492.         // flip it around & draw it from the end to the start.  This prevents the model from going
  1493.         // through the tesla mine (instead it goes through the target)
  1494.         if ((b->model == cl_mod_lightning) && (d <= model_length))
  1495.         {
  1496. //            Com_Printf ("special case\n");
  1497.             VectorCopy (b->end, ent.origin);
  1498.             // offset to push beam outside of tesla model (negative because dist is from end to start
  1499.             // for this beam)
  1500. //            for (j=0 ; j<3 ; j++)
  1501. //                ent.origin[j] -= dist[j]*10.0;
  1502.             ent.model = b->model;
  1503.             ent.flags = RF_FULLBRIGHT;
  1504.             ent.angles[0] = pitch;
  1505.             ent.angles[1] = yaw;
  1506.             ent.angles[2] = rand()%360;
  1507.             V_AddEntity (&ent);            
  1508.             return;
  1509.         }
  1510.         while (d > 0)
  1511.         {
  1512.             VectorCopy (org, ent.origin);
  1513.             ent.model = b->model;
  1514.             if (b->model == cl_mod_lightning)
  1515.             {
  1516.                 ent.flags = RF_FULLBRIGHT;
  1517.                 ent.angles[0] = -pitch;
  1518.                 ent.angles[1] = yaw + 180.0;
  1519.                 ent.angles[2] = rand()%360;
  1520.             }
  1521.             else
  1522.             {
  1523.                 ent.angles[0] = pitch;
  1524.                 ent.angles[1] = yaw;
  1525.                 ent.angles[2] = rand()%360;
  1526.             }
  1527.             
  1528. //            Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
  1529.             V_AddEntity (&ent);
  1530.  
  1531.             for (j=0 ; j<3 ; j++)
  1532.                 org[j] += dist[j]*len;
  1533.             d -= model_length;
  1534.         }
  1535.     }
  1536. }
  1537.  
  1538.  
  1539. /*
  1540. //                Com_Printf ("Endpoint:  %f %f %f\n", b->end[0], b->end[1], b->end[2]);
  1541. //                Com_Printf ("Pred View Angles:  %f %f %f\n", cl.predicted_angles[0], cl.predicted_angles[1], cl.predicted_angles[2]);
  1542. //                Com_Printf ("Act View Angles: %f %f %f\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2]);
  1543. //                VectorCopy (cl.predicted_origin, b->start);
  1544. //                b->start[2] += 22;    // adjust for view height
  1545. //                if (fabs(cl.refdef.vieworg[2] - b->start[2]) >= 10) {
  1546. //                    b->start[2] = cl.refdef.vieworg[2];
  1547. //                }
  1548.  
  1549. //                Com_Printf ("Time:  %d %d %f\n", cl.time, cls.realtime, cls.frametime);
  1550. */
  1551.  
  1552. extern cvar_t *hand;
  1553.  
  1554. /*
  1555. =================
  1556. ROGUE - draw player locked beams
  1557. CL_AddPlayerBeams
  1558. =================
  1559. */
  1560. void CL_AddPlayerBeams (void)
  1561. {
  1562.     int            i,j;
  1563.     beam_t        *b;
  1564.     vec3_t        dist, org;
  1565.     float        d;
  1566.     entity_t    ent;
  1567.     float        yaw, pitch;
  1568.     float        forward;
  1569.     float        len, steps;
  1570.     int            framenum;
  1571.     float        model_length;
  1572.     
  1573.     float        hand_multiplier;
  1574.     frame_t        *oldframe;
  1575.     player_state_t    *ps, *ops;
  1576.  
  1577. //PMM
  1578.     if (hand)
  1579.     {
  1580.         if (hand->value == 2)
  1581.             hand_multiplier = 0;
  1582.         else if (hand->value == 1)
  1583.             hand_multiplier = -1;
  1584.         else
  1585.             hand_multiplier = 1;
  1586.     }
  1587.     else 
  1588.     {
  1589.         hand_multiplier = 1;
  1590.     }
  1591. //PMM
  1592.  
  1593. // update beams
  1594.     for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  1595.     {
  1596.         vec3_t        f,r,u;
  1597.         if (!b->model || b->endtime < cl.time)
  1598.             continue;
  1599.  
  1600.         if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1601.         {
  1602.  
  1603.             // if coming from the player, update the start position
  1604.             if (b->entity == cl.playernum+1)    // entity 0 is the world
  1605.             {    
  1606.                 // set up gun position
  1607.                 // code straight out of CL_AddViewWeapon
  1608.                 ps = &cl.frame.playerstate;
  1609.                 j = (cl.frame.serverframe - 1) & UPDATE_MASK;
  1610.                 oldframe = &cl.frames[j];
  1611.                 if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
  1612.                     oldframe = &cl.frame;        // previous frame was dropped or involid
  1613.                 ops = &oldframe->playerstate;
  1614.                 for (j=0 ; j<3 ; j++)
  1615.                 {
  1616.                     b->start[j] = cl.refdef.vieworg[j] + ops->gunoffset[j]
  1617.                         + cl.lerpfrac * (ps->gunoffset[j] - ops->gunoffset[j]);
  1618.                 }
  1619.                 VectorMA (b->start, (hand_multiplier * b->offset[0]), cl.v_right, org);
  1620.                 VectorMA (     org, b->offset[1], cl.v_forward, org);
  1621.                 VectorMA (     org, b->offset[2], cl.v_up, org);
  1622.                 if ((hand) && (hand->value == 2)) {
  1623.                     VectorMA (org, -1, cl.v_up, org);
  1624.                 }
  1625.                 // FIXME - take these out when final
  1626.                 VectorCopy (cl.v_right, r);
  1627.                 VectorCopy (cl.v_forward, f);
  1628.                 VectorCopy (cl.v_up, u);
  1629.  
  1630.             }
  1631.             else
  1632.                 VectorCopy (b->start, org);
  1633.         }
  1634.         else
  1635.         {
  1636.             // if coming from the player, update the start position
  1637.             if (b->entity == cl.playernum+1)    // entity 0 is the world
  1638.             {
  1639.                 VectorCopy (cl.refdef.vieworg, b->start);
  1640.                 b->start[2] -= 22;    // adjust for view height
  1641.             }
  1642.             VectorAdd (b->start, b->offset, org);
  1643.         }
  1644.  
  1645.     // calculate pitch and yaw
  1646.         VectorSubtract (b->end, org, dist);
  1647.  
  1648. //PMM
  1649.         if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1))
  1650.         {
  1651.             vec_t len;
  1652.  
  1653.             len = VectorLength (dist);
  1654.             VectorScale (f, len, dist);
  1655.             VectorMA (dist, (hand_multiplier * b->offset[0]), r, dist);
  1656.             VectorMA (dist, b->offset[1], f, dist);
  1657.             VectorMA (dist, b->offset[2], u, dist);
  1658.             if ((hand) && (hand->value == 2)) {
  1659.                 VectorMA (org, -1, cl.v_up, org);
  1660.             }
  1661.         }
  1662. //PMM
  1663.  
  1664.         if (dist[1] == 0 && dist[0] == 0)
  1665.         {
  1666.             yaw = 0;
  1667.             if (dist[2] > 0)
  1668.                 pitch = 90;
  1669.             else
  1670.                 pitch = 270;
  1671.         }
  1672.         else
  1673.         {
  1674.     // PMM - fixed to correct for pitch of 0
  1675.             if (dist[0])
  1676.                 yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
  1677.             else if (dist[1] > 0)
  1678.                 yaw = 90;
  1679.             else
  1680.                 yaw = 270;
  1681.             if (yaw < 0)
  1682.                 yaw += 360;
  1683.     
  1684.             forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  1685.             pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
  1686.             if (pitch < 0)
  1687.                 pitch += 360.0;
  1688.         }
  1689.         
  1690.         if (cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1691.         {
  1692.             if (b->entity != cl.playernum+1)
  1693.             {
  1694.                 framenum = 2;
  1695. //                Com_Printf ("Third person\n");
  1696.                 ent.angles[0] = -pitch;
  1697.                 ent.angles[1] = yaw + 180.0;
  1698.                 ent.angles[2] = 0;
  1699. //                Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, b->offset[0], b->offset[1], b->offset[2]);
  1700.                 AngleVectors(ent.angles, f, r, u);
  1701.                     
  1702.                 // if it's a non-origin offset, it's a player, so use the hardcoded player offset
  1703.                 if (!VectorCompare (b->offset, vec3_origin))
  1704.                 {
  1705.                     VectorMA (org, -(b->offset[0])+1, r, org);
  1706.                     VectorMA (org, -(b->offset[1]), f, org);
  1707.                     VectorMA (org, -(b->offset[2])-10, u, org);
  1708.                 }
  1709.                 else
  1710.                 {
  1711.                     // if it's a monster, do the particle effect
  1712.                     CL_MonsterPlasma_Shell(b->start);
  1713.                 }
  1714.             }
  1715.             else
  1716.             {
  1717.                 framenum = 1;
  1718.             }
  1719.         }
  1720.  
  1721.         // if it's the heatbeam, draw the particle effect
  1722.         if ((cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1)))
  1723.         {
  1724.             CL_Heatbeam (org, dist);
  1725.         }
  1726.  
  1727.     // add new entities for the beams
  1728.         d = VectorNormalize(dist);
  1729.  
  1730.         memset (&ent, 0, sizeof(ent));
  1731.         if (b->model == cl_mod_heatbeam)
  1732.         {
  1733.             model_length = 32.0;
  1734.         }
  1735.         else if (b->model == cl_mod_lightning)
  1736.         {
  1737.             model_length = 35.0;
  1738.             d-= 20.0;  // correction so it doesn't end in middle of tesla
  1739.         }
  1740.         else
  1741.         {
  1742.             model_length = 30.0;
  1743.         }
  1744.         steps = ceil(d/model_length);
  1745.         len = (d-model_length)/(steps-1);
  1746.  
  1747.         // PMM - special case for lightning model .. if the real length is shorter than the model,
  1748.         // flip it around & draw it from the end to the start.  This prevents the model from going
  1749.         // through the tesla mine (instead it goes through the target)
  1750.         if ((b->model == cl_mod_lightning) && (d <= model_length))
  1751.         {
  1752. //            Com_Printf ("special case\n");
  1753.             VectorCopy (b->end, ent.origin);
  1754.             // offset to push beam outside of tesla model (negative because dist is from end to start
  1755.             // for this beam)
  1756. //            for (j=0 ; j<3 ; j++)
  1757. //                ent.origin[j] -= dist[j]*10.0;
  1758.             ent.model = b->model;
  1759.             ent.flags = RF_FULLBRIGHT;
  1760.             ent.angles[0] = pitch;
  1761.             ent.angles[1] = yaw;
  1762.             ent.angles[2] = rand()%360;
  1763.             V_AddEntity (&ent);            
  1764.             return;
  1765.         }
  1766.         while (d > 0)
  1767.         {
  1768.             VectorCopy (org, ent.origin);
  1769.             ent.model = b->model;
  1770.             if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1771.             {
  1772. //                ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  1773. //                ent.alpha = 0.3;
  1774.                 ent.flags = RF_FULLBRIGHT;
  1775.                 ent.angles[0] = -pitch;
  1776.                 ent.angles[1] = yaw + 180.0;
  1777.                 ent.angles[2] = (cl.time) % 360;
  1778. //                ent.angles[2] = rand()%360;
  1779.                 ent.frame = framenum;
  1780.             }
  1781.             else if (b->model == cl_mod_lightning)
  1782.             {
  1783.                 ent.flags = RF_FULLBRIGHT;
  1784.                 ent.angles[0] = -pitch;
  1785.                 ent.angles[1] = yaw + 180.0;
  1786.                 ent.angles[2] = rand()%360;
  1787.             }
  1788.             else
  1789.             {
  1790.                 ent.angles[0] = pitch;
  1791.                 ent.angles[1] = yaw;
  1792.                 ent.angles[2] = rand()%360;
  1793.             }
  1794.             
  1795. //            Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
  1796.             V_AddEntity (&ent);
  1797.  
  1798.             for (j=0 ; j<3 ; j++)
  1799.                 org[j] += dist[j]*len;
  1800.             d -= model_length;
  1801.         }
  1802.     }
  1803. }
  1804.  
  1805. /*
  1806. =================
  1807. CL_AddExplosions
  1808. =================
  1809. */
  1810. void CL_AddExplosions (void)
  1811. {
  1812.     entity_t    *ent;
  1813.     int            i;
  1814.     explosion_t    *ex;
  1815.     float        frac;
  1816.     int            f;
  1817.  
  1818.     memset (&ent, 0, sizeof(ent));
  1819.  
  1820.     for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
  1821.     {
  1822.         if (ex->type == ex_free)
  1823.             continue;
  1824.         frac = (cl.time - ex->start)/100.0;
  1825.         f = floor(frac);
  1826.  
  1827.         ent = &ex->ent;
  1828.  
  1829.         switch (ex->type)
  1830.         {
  1831.         case ex_mflash:
  1832.             if (f >= ex->frames-1)
  1833.                 ex->type = ex_free;
  1834.             break;
  1835.         case ex_misc:
  1836.             if (f >= ex->frames-1)
  1837.             {
  1838.                 ex->type = ex_free;
  1839.                 break;
  1840.             }
  1841.             ent->alpha = 1.0 - frac/(ex->frames-1);
  1842.             break;
  1843.         case ex_flash:
  1844.             if (f >= 1)
  1845.             {
  1846.                 ex->type = ex_free;
  1847.                 break;
  1848.             }
  1849.             ent->alpha = 1.0;
  1850.             break;
  1851.         case ex_poly:
  1852.             if (f >= ex->frames-1)
  1853.             {
  1854.                 ex->type = ex_free;
  1855.                 break;
  1856.             }
  1857.  
  1858.             ent->alpha = (16.0 - (float)f)/16.0;
  1859.  
  1860.             if (f < 10)
  1861.             {
  1862.                 ent->skinnum = (f>>1);
  1863.                 if (ent->skinnum < 0)
  1864.                     ent->skinnum = 0;
  1865.             }
  1866.             else
  1867.             {
  1868.                 ent->flags |= RF_TRANSLUCENT;
  1869.                 if (f < 13)
  1870.                     ent->skinnum = 5;
  1871.                 else
  1872.                     ent->skinnum = 6;
  1873.             }
  1874.             break;
  1875.         case ex_poly2:
  1876.             if (f >= ex->frames-1)
  1877.             {
  1878.                 ex->type = ex_free;
  1879.                 break;
  1880.             }
  1881.  
  1882.             ent->alpha = (5.0 - (float)f)/5.0;
  1883.             ent->skinnum = 0;
  1884.             ent->flags |= RF_TRANSLUCENT;
  1885.             break;
  1886.         }
  1887.  
  1888.         if (ex->type == ex_free)
  1889.             continue;
  1890.         if (ex->light)
  1891.         {
  1892.             V_AddLight (ent->origin, ex->light*ent->alpha,
  1893.                 ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]);
  1894.         }
  1895.  
  1896.         VectorCopy (ent->origin, ent->oldorigin);
  1897.  
  1898.         if (f < 0)
  1899.             f = 0;
  1900.         ent->frame = ex->baseframe + f + 1;
  1901.         ent->oldframe = ex->baseframe + f;
  1902.         ent->backlerp = 1.0 - cl.lerpfrac;
  1903.  
  1904.         V_AddEntity (ent);
  1905.     }
  1906. }
  1907.  
  1908.  
  1909. /*
  1910. =================
  1911. CL_AddLasers
  1912. =================
  1913. */
  1914. void CL_AddLasers (void)
  1915. {
  1916.     laser_t        *l;
  1917.     int            i;
  1918.  
  1919.     for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
  1920.     {
  1921.         if (l->endtime >= cl.time)
  1922.             V_AddEntity (&l->ent);
  1923.     }
  1924. }
  1925.  
  1926. /* PMM - CL_Sustains */
  1927. void CL_ProcessSustain ()
  1928. {
  1929.     cl_sustain_t    *s;
  1930.     int                i;
  1931.  
  1932.     for (i=0, s=cl_sustains; i< MAX_SUSTAINS; i++, s++)
  1933.     {
  1934.         if (s->id)
  1935.             if ((s->endtime >= cl.time) && (cl.time >= s->nextthink))
  1936.             {
  1937. //                Com_Printf ("think %d %d %d\n", cl.time, s->nextthink, s->thinkinterval);
  1938.                 s->think (s);
  1939.             }
  1940.             else if (s->endtime < cl.time)
  1941.                 s->id = 0;
  1942.     }
  1943. }
  1944.  
  1945. /*
  1946. =================
  1947. CL_AddTEnts
  1948. =================
  1949. */
  1950. void CL_AddTEnts (void)
  1951. {
  1952.     CL_AddBeams ();
  1953.     // PMM - draw plasma beams
  1954.     CL_AddPlayerBeams ();
  1955.     CL_AddExplosions ();
  1956.     CL_AddLasers ();
  1957.     // PMM - set up sustain
  1958.     CL_ProcessSustain();
  1959. }
  1960.